package net 
{
	import event.CommEvent;
	import event.SocketEvent;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	/**
	 * ...
	 * @author carlor
	 */
	public class GSocket extends Socket
	{
		//包头标志（心跳包）
		static public const PACKET_HEADFLAG_HEART    : int = 1;
		//包头标志（消息胞）
		static public const PACKET_HEADFLAG_PACKAGE  : int = 2;
		//包头标志（握手包）
		static public const PACKET_HEADFLAG_HANDSHAKE: int = 3;
		//间隔（秒）
		static public const INTERVAL : int = 10;
		//超时时间（秒）
		static public const TIMEOUT  : int = 30;
		//请求心跳数据
		static public const HEART_REQ: int = -1;
		//响应心跳数据
		static public const HEART_REP: int = -2;
		
		
		//连接的主机ip
		private var _host    : String = "";
		// 连接主机的端口
		private var _port    : int;
		// 是否保持心跳
		private var _isKeepAlive: Boolean = true;
		// 连接是否在使用中
		private var _isUsed  : Boolean = false;
		// 服务器请求回调。
		private var _callback: Function = null;
		//接收的缓冲数据
		private var _tempBuff: ByteArray = new ByteArray();
		// 心跳Timer
		private var _pulseTimer: Timer = null;
		// 时间轴
		private var _timeData : int = 0;
		
		
		public function GSocket(host: String="", port: int=0) 
		{
			super(host, port);
			super.addEventListener(ProgressEvent.SOCKET_DATA, onSocketDataHandler);
			super.addEventListener(Event.CLOSE, onSocketClose);
			super.addEventListener(Event.CONNECT, onSocketConnect);
			super.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
			super.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			if (host.length > 0 && port > 0)
				connect(host, port);
		}
		
		override public function addEventListener(type: String, listener: Function, useCapture: Boolean = false, priority: int = 0, useWeakReference: Boolean = false): void
		{
			if (! (type == ProgressEvent.SOCKET_DATA || type == Event.CLOSE || type == Event.CONNECT || type == IOErrorEvent.IO_ERROR || type == SecurityErrorEvent.SECURITY_ERROR))
				super.addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		
		override public function connect(host: String, port: int): void
		{
			this._host = host;
			this._port = port;
			super.connect(host, port);
		}
		
		override public function close(): void
		{
			if (connected) super.close();
			if (_pulseTimer.running)	_pulseTimer.stop();
			
			_pulseTimer.removeEventListener(TimerEvent.TIMER,  onAliveHandler);
			_pulseTimer = null;
		}
		
		public function readLong(): Number
		{
			return Number(super.readInt()) * 10000000 + Number(super.readInt());
		}
		
		public function writeLong(value: Number): void
		{
			this.writeInt(int(value / 100000000));
			this.writeInt(int(value % 100000000));
		}
		
		private function onSocketDataHandler(e: ProgressEvent): void
		{
			try {
				this.readBytes(_tempBuff, _tempBuff.length, this.bytesAvailable);
				_tempBuff.position = 0;
				var curBufLen: int = _tempBuff.length;
				//消息指针
				var msgPos: int = 0;
				//回补长度
				var anaplerosisLen: int = 0;
				
				while (true) {
					//消息标识都没有
					if (curBufLen < 1) break;
					
					//消息标识
					var flag: int = _tempBuff.readByte();
					curBufLen -= 1;
					msgPos += 1;
					
					//心跳包
					if (flag == PACKET_HEADFLAG_HEART) {
						//心跳包的那个字节没到
						if (curBufLen < 1) {
							anaplerosisLen = 1;
							break;
						}
						
						var type: int = _tempBuff.readByte();
						curBufLen -= 1;
						msgPos += 1;
						
						if (type == HEART_REQ) {
							//服务器发来的心跳请求
							_timeData = getTimer();
						
						}else if (type == HEART_REP) {
							//服务器发来的心跳响应
						}else {
							//心跳数据错误
							dispatchEvent(new SocketEvent(SocketEvent.SOCKET_DATA_HEART_ERROR));
						}
					}
					//其他包（主要是业务通讯包）
					else if (flag == PACKET_HEADFLAG_PACKAGE || flag == PACKET_HEADFLAG_HANDSHAKE) {
						//业务包的长度没到
						if (curBufLen < 2) {
							anaplerosisLen = 1;
							break;
						}
						
						//消息长度
						//注：这个长度实际上包括short本身，所以还要再减2
						var msgLen: int = _tempBuff.readUnsignedShort() - 2;
						curBufLen -= 2;
						msgPos += 2;
						// 如果消息长度大于剩余的字节数，说明包不完整
						if (msgLen > curBufLen) {
							anaplerosisLen = 3;
							break;
						}
						var pkgBuff: ByteArray = new ByteArray();
						_tempBuff.readBytes(pkgBuff, 0, msgLen);
						curBufLen -= msgLen;
						msgPos += msgLen;
						
						//业务包事件
						if (flag == PACKET_HEADFLAG_PACKAGE) {
							if (_callback != null)
								_callback(pkgBuff);
						}
						//握手包事件
						else if (flag == PACKET_HEADFLAG_HANDSHAKE)
							this.dispatchEvent(new SocketEvent(SocketEvent.SOCKET_DATA_HANDSHAKE, pkgBuff))
					}else
						this.dispatchEvent(new SocketEvent(SocketEvent.SOCKET_DATA_HEAD_ERROR));
				}				
				// 还有数据未处理
				if ( curBufLen != 0 ) {
					if(msgPos < _tempBuff.length){
						//只保留缓冲中，不完整的这个包的数据
						var moveBuff: ByteArray = _tempBuff;
						_tempBuff = new ByteArray();
						moveBuff.position = msgPos - anaplerosisLen;
						moveBuff.readBytes(_tempBuff);
						moveBuff = null;									
					}else
						_tempBuff.clear()
				}else
					_tempBuff.clear();

			} catch (err: Error) {
				this.dispatchEvent(new SocketEvent(SocketEvent.SOCKET_DATA_HEAD_ERROR, err.getStackTrace()));
			}
		}
		
		private function onSocketClose(e: Event): void
		{
			dispatchEvent(new SocketEvent(SocketEvent.SOCKET_CLOSE, e));
		}
		
		private function onSocketConnect(e: Event): void
		{
			dispatchEvent(new SocketEvent(SocketEvent.SOCKET_CONNECT, e));
		}
		
		private function onIoError(e: IOErrorEvent): void
		{
			dispatchEvent(new SocketEvent(SocketEvent.SOCKET_IO_ERROR, e));
		}
		
		private function onSecurityError(e: SecurityErrorEvent): void
		{
			dispatchEvent(new SocketEvent(SocketEvent.SOCKET_SECURITY_ERROR, e));
		}
		
		/*
		 * 启动心跳机制
		 */
		public function startAlive(): void
		{
			if (_isKeepAlive) {
				if (_pulseTimer == null)
					_pulseTimer = new Timer(INTERVAL * 1000);
				if (! _pulseTimer.hasEventListener(TimerEvent.TIMER))
					_pulseTimer.addEventListener(TimerEvent.TIMER, onAliveHandler);
				if (! _pulseTimer.running)
					_pulseTimer.start();
			}
		}
		
		private function onAliveHandler(e: TimerEvent): void
		{
			//发送心跳脉冲
			if (connected) {
				this.writeByte(PACKET_HEADFLAG_HEART);
				this.writeByte(HEART_REQ);
				this.flush();
			}
			if ((getTimer() - _timeData) > TIMEOUT * 1000) {
				this.dispatchEvent(new SocketEvent(SocketEvent.SOCKET_TIME_OUT));
				close();
			}
		}
		
		public function set callBack(value: Function): void
		{
			_callback = value;
		}
	}

}